package util

import (
	"errors"
	"math/rand"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

const sign_key = "hello_chat"

var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

type CustomClaim struct {
	UserName string
	jwt.RegisteredClaims
}

func randStr(str_len int) string {
	rand_bytes := make([]rune, str_len)
	for i := range rand_bytes {
		rand_bytes[i] = letters[rand.Intn(len(letters))]
	}
	return string(rand_bytes)
}

func GenerateToken(userName string) (string, error) {
	claim := CustomClaim{
		UserName: userName,
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:    "Chat_Server",
			Subject:   userName,
			Audience:  jwt.ClaimStrings{"Android"},
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
			NotBefore: jwt.NewNumericDate(time.Now()),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			ID:        randStr(10),
		},
	}
	s, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claim).SignedString([]byte(sign_key))
	return s, err
}

func ParseToken(token_string string) (*CustomClaim, error) {
	token, err := jwt.ParseWithClaims(token_string, &CustomClaim{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(sign_key), nil //返回签名密钥
	})
	if err != nil {
		return nil, err
	}

	if !token.Valid {
		return nil, errors.New("claim invalid")
	}

	claims, ok := token.Claims.(*CustomClaim)
	if !ok {
		return nil, errors.New("invalid claim type")
	}

	return claims, nil
}
